package com.zcz.authentication.service.impl;

import com.zcz.authentication.bean.Quanxian;
import com.zcz.authentication.config.UserRealm;
import com.zcz.authentication.mapper.QuanxianMapper;
import com.zcz.authentication.service.ShiroService;
import com.zcz.authentication.util.FebsException;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.filter.mgt.DefaultFilterChainManager;
import org.apache.shiro.web.filter.mgt.PathMatchingFilterChainResolver;
import org.apache.shiro.web.servlet.AbstractShiroFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@Service
public class ShiroServiceImpl implements ShiroService {
	@Autowired
	private QuanxianMapper quanxianMapper;
	@Autowired
	private UserRealm userRealm;
	
	@Override
	public Map<String, String> loadFilterChainDefinitionMap() {
		System.err.println("执行；拉");
		// 权限控制map
        Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
        // 配置过滤:不会被拦截的链接 -> 放行 start ----------------------------------------------------------
        // 放行Swagger2页面，需要放行这些
        filterChainDefinitionMap.put("/swagger-ui.html","anon");
        filterChainDefinitionMap.put("/swagger/**","anon");
        filterChainDefinitionMap.put("/webjars/**", "anon");
        filterChainDefinitionMap.put("/swagger-resources/**","anon");
        filterChainDefinitionMap.put("/v2/**","anon");
        filterChainDefinitionMap.put("/static/**", "anon");

        // 登陆
        filterChainDefinitionMap.put("/api/auth/login/**", "anon");
        // 三方登录
        filterChainDefinitionMap.put("/api/auth/loginByQQ", "anon");
        filterChainDefinitionMap.put("/api/auth/afterlogin.do", "anon");
        // 退出
        filterChainDefinitionMap.put("/api/auth/logout", "anon");
        // 放行未授权接口，重定向使用
        filterChainDefinitionMap.put("/api/auth/unauth", "anon");
        // token过期接口
        filterChainDefinitionMap.put("/api/auth/tokenExpired", "anon");
        // 被挤下线
        filterChainDefinitionMap.put("/api/auth/downline", "anon");
        
        filterChainDefinitionMap.put("/holle/thymeleaf", "anon");
        filterChainDefinitionMap.put("/holle/login", "anon");
        // 放行 end ----------------------------------------------------------

       
        // 从数据库或缓存中查取出来的url与resources对应则不会被拦截 放行
		List<Quanxian> permissionList = quanxianMapper.selectAllQuanxian();
		//List<Menu> permissionList = menuMapper.selectList( null );
        if ( permissionList != null ) {
        	System.err.println("执行；拉");
        	for (Quanxian quanxian : permissionList) {
        		//filterMap.put("/holle/add", "perms[user:add]");
        		filterChainDefinitionMap.put( quanxian.getUrl(),"perms["+quanxian.getQuanxian()+"]" );
			}
        // ⑤ 认证登录  【注：map不能存放相同key】
        filterChainDefinitionMap.put("/**", "authc");
        filterChainDefinitionMap.put("/holle/logout", "logout");
        
       
        }
        return filterChainDefinitionMap;
	}

	@Override
	public void updatePermission(ShiroFilterFactoryBean shiroFilterFactoryBean) throws FebsException {
	//public void updatePermission(ShiroFilterFactoryBean shiroFilterFactoryBean, Integer roleId, Boolean isRemoveSession) throws FebsException {
		 synchronized (this) {
	            AbstractShiroFilter shiroFilter;
	            try {
	                shiroFilter = (AbstractShiroFilter) shiroFilterFactoryBean.getObject();
	            } catch (Exception e) {
	                throw new FebsException("get ShiroFilter from shiroFilterFactoryBean error!");
	            }
	            PathMatchingFilterChainResolver filterChainResolver = (PathMatchingFilterChainResolver) shiroFilter.getFilterChainResolver();
	            DefaultFilterChainManager manager = (DefaultFilterChainManager) filterChainResolver.getFilterChainManager();

	            // 清空拦截管理器中的存储
	            manager.getFilterChains().clear();
	            // 清空拦截工厂中的存储,如果不清空这里,还会把之前的带进去
	            // 如果仅仅是更新的话,可以根据这里的 map 遍历数据修改,重新整理好权限再一起添加
	            shiroFilterFactoryBean.getFilterChainDefinitionMap().clear();
	            // 动态查询数据库中所有权限
	            shiroFilterFactoryBean.setFilterChainDefinitionMap(loadFilterChainDefinitionMap());
	            // 重新构建生成拦截
	            Map<String, String> chains = shiroFilterFactoryBean.getFilterChainDefinitionMap();
	            for (Map.Entry<String, String> entry : chains.entrySet()) {
	                manager.createChain(entry.getKey(), entry.getValue());
	                //System.err.println( entry.getKey()+"+++"+ entry.getValue());
	            }
	            log.info("--------------- 动态生成url权限成功！ ---------------");
	            //清除所有缓存
	            userRealm.claerCached();
	     
	        }
		
	}

	

	@Override
	public void updatePermissionByRoleId(Integer roleId, Boolean isRemoveSession) {
//		// 查询当前角色的用户shiro缓存信息 -> 实现动态权限
//        List<User> userList = userMapper.selectUserByRoleId(roleId);
//        // 删除当前角色关联的用户缓存信息,用户再次访问接口时会重新授权 ; isRemoveSession为true时删除Session -> 即强制用户退出
//        if (  userList !=null ) {
//            for (User user : userList) {
//                ShiroUtils.deleteCache(user.getUsername(), isRemoveSession);
//            }
//        }
//        log.info("--------------- 动态修改用户权限成功！ ---------------");
   }
		
	

	
	
}